#ifndef SHAKE_H_
#define SHAKE_H_
#include "esmd_types.h"
#include "comm.h"
#include "elemtab.h"
enum shake_cond_type {
  SHAKE_MASS,
  SHAKE_ANGLE,
  SHAKE_BOND,
  SHAKE_END
};
enum shake_type {
  NOSHAKE = 0,
  SHAKE2 = 1,
  SHAKE3 = 2,
  SHAKE4 = 3,
  SHAKE3ANGLE=4
};

typedef struct shake_cond {
  union {
    struct {
      double lo, hi;
    } mass;
    struct {
      int i, j, k;
    } angle;
    struct {
      int i, j;
    } bond;
  } cond;
  int type;
} shake_cond_t;
typedef struct shake_types {
  int *buf;
  int ntypes, size;
} shake_types_t;
#define GET_SHAKE_TYPES(ptr) ((ptr)->buf)
#define GET_SHAKE_BONDS(ptr) ((ptr)->buf + ntypes)
#define GET_SHAKE_ANGLES(ptr) ((ptr)->buf + ntypes * (ntypes + 1))
//function signatures
shake_cond_t *parse_shake_cond(const char *condstr, elemtab_t *elemtab);
void parse_shake_types(shake_types_t *shakes, const char *condstr, elemtab_t *elemtab);
void find_clusters(cellgrid_t *grid, shake_cond_t *conds, int ntypes, real *bond_len, real *angle_len);
void find_clusters_typed(cellgrid_t *grid, shake_types_t *shakes, int ntypes, real *bond_len, real *angle_len);
void shake2(celldata_t *cell, int i, real dtfsq, real tol, int maxiter);
void shake2_nodt(celldata_t *cell, int i, real tol, int maxiter);
void shake3(celldata_t *cell, int i, real dtfsq, real tol, int maxiter);
void shake3angle(celldata_t *cell, int i, real dtfsq, real tol, int maxiter);
void shake4(celldata_t *cell, int i, real dtfsq, real tol, int maxiter);
void shake3_nodt(celldata_t *cell, int i, real tol, int maxiter);
void shake3angle_nodt(celldata_t *cell, int i, real tol, int maxiter);
void shake4_nodt(celldata_t *cell, int i, real tol, int maxiter);
void unconstrained_update(cellgrid_t *grid, real dtv, real dtfsq);
void do_shake(cellgrid_t *grid, real dtfsq);
void correct_coordinates_dt(cellgrid_t *grid, mpp_t *mpp, real dtv, real dtfsq);
void correct_coordinates(cellgrid_t *grid, mpp_t *mpp);
void shake_setup(cellgrid_t *grid, mpp_t *mpp, real dt, real ftm2v);
void shake_post_force(cellgrid_t *grid, mpp_t *mpp, real dt, real ftm2v);
//end function signatures
#endif
